<template>
    <div class="row">
        <h3>{{api.api_name}}</h3>
        <div class="panel panel-default">
            <div class="panel-heading">请求参数相关</div>
            <div class="panel-body">
                <widget-pane title="接口地址" :body="api.path"></widget-pane>
                <widget-pane title="请求方法" :body="api.method"></widget-pane>
                <widget-pane title="请求参数Content-type类型" :body="api.content_type"></widget-pane>
                <widget-pane title="接口说明" :body="api.remark"></widget-pane>
            </div>
            <div class="panel panel-default">
                <div class="panel-heading">提交body参数</div>
                <div class="panel-body">
                    <table class="table table-striped">
                        <thead>
                        <tr class="success">
                            <th>参数名</th>
                            <th>参数类型</th>
                            <th>是否必填</th>
                            <th>默认值</th>
                            <th>参数说明</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="param in api.request_params">
                            <td>{{param.name}}</td>
                            <td>{{param.type}}</td>
                            <td>{{param.required}}</td>
                            <td>{{param.default_value}}</td>
                            <td>{{param.remark}}</td>
                        </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
        <div class="panel panel-info">
            <div class="panel-heading">返回参数相关</div>
            <div class="panel-body">
                <widget-pane title="返回参数类型" :body="api.response.data_type"></widget-pane>
                <widget-pane title="返回参数结构" :html="api.response.structure"></widget-pane>
                <widget-pane title="返回参数demo" :html="api.response.demo"></widget-pane>
            </div>
        </div>
        <div class="panel panel-warning">
            <div class="panel-heading">接口在线测试</div>
            <div class="panel-body">
                <form action="" name="test_form" :enctype="api.content_type">
                    <div class="form-group">
                        <label>代理设置</label>
                        <input type="text" class="form-control" name="http_proxy" placeholder="">
                        <p class="help-block">设置接口请求代理(格式:http://ip:端口)</p>
                    </div>
                    <div class="form-group">
                        <label>环境</label>
                        <select name="env" class="form-control">
                            <option value="test">测试</option>
                        </select>
                    </div>
                    <div class="form-group" v-for="preset in preset_param">
                        <label>{{preset.key}}</label>
                        <input class="form-control" type="text"
                               :name="preset.key"
                               v-model="preset.value">
                    </div>
                    <div class="form-group" v-for="param in api_test.request">
                        <label>{{param.name}}</label>
                        <input class="form-control"
                               :type="getInput(param)"
                               :name="param.name"
                               v-model="param.default_value">
                        <p class="help-block">{{param.remark}}</p>
                    </div>
                </form>

                <div class="form-group">
                    <button v-on:click="submit" class="btn btn-default">提交</button>
                </div>

            </div>
        </div>
        <div class="panel panel-danger" id="test_result">
            <div class="panel-heading">测试返回数据</div>
            <div class="panel-body">
                <pre v-html="response"></pre>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "Api",
        created: function () {
            this.loadApi();
        },
        props: ['api_id', 'project_id'],
        data() {
            return {
                api: {
                    request: {},
                    response: {
                        data_type: 'JSON'
                    }
                },
                api_test: {
                    response: '此处展示返回结果'
                },
                preset_param: {}
            }
        },
        computed: {
            response: function () {
                return this.formatJson(this.api_test.response)
            }
        },
        watch: {
            '$route'() {
                this.api_id = this.$route.params.api_id;
                this.project_id = this.$route.params.project_id;
                this.loadApi();
            }
        },
        methods: {
            submit: function (e) {
                e.preventDefault();
                let form_data = new FormData(document.forms.namedItem('test_form'));
                axios({
                    method: 'post',
                    url: '/api/debug/' + this.api_id,
                    data: form_data,
                }).then(this.handleResponse).catch(this.handleError);
            },
            handleError: function (error) {
                this.api_test.response = error.message;
            },
            handleResponse: function (response) {
                this.api_test.response = response.data;
            },
            handleLoadApi: function (response) {
                let api = response.data.data.api;
                this.api = {
                    api_id: this.api_id,
                    api_name: api.api_name,
                    remark: api.remark,
                    domain: api.domain,
                    path: api.path,
                    version: api.version,
                    method: api.method,
                    content_type: api.content_type,
                    category_id: api.category_id,
                    project_id: api.project_id,
                    created_at: api.created_at,
                    updated_at: api.updated_at,
                    request_params: [],
                    response: {},
                    request_url: api.request_url
                };
                for (let i in api.request) {
                    this.api.request_params.push(
                        {
                            name: api.request[i].param_name,
                            type: api.request[i].param_type,
                            default_value: api.request[i].default,
                            required: api.request[i].required,
                            remark: api.request[i].remark,
                        }
                    );
                }
                this.api.response = {
                    data_type: api.response.content_type,
                    structure: "<pre>" + api.response.body + "</pre>",
                    demo: "<pre class='pre-scrollable'>" + api.response.demo + "</pre>"
                };
                this.api_test.request = this.api.request_params;
            },
            loadApi: function () {
                axios({
                    method: 'get',
                    url: '/api/api/' + this.api_id,
                }).then(this.handleLoadApi);
                axios({
                    method: 'get',
                    url: '/api/request_preset?project_id=' + this.project_id,
                }).then(this.handlePresetBody);
            },
            handlePresetBody: function (response) {
                this.preset_param = response.data.data;
            },
            getInput: function (param) {
                switch (param.type) {
                    default:
                        return 'text';
                    case 'file':
                        return 'file';
                }
            },
            repeat: function (s, count) {
                return new Array(count + 1).join(s);
            },
            formatJson: function (json) {
                let jsonUtil = {
                    //定义换行符
                    n: "<br />",
                    //定义制表符
                    t: "&nbsp;&nbsp;&nbsp;&nbsp;",
                    //转换String
                    convertToString: function (obj) {
                        return this.__writeObj(obj, 1);
                    },
                    //写对象
                    __writeObj: function (obj    //对象
                        , level             //层次（基数为1）
                        , isInArray) {       //此对象是否在一个集合内
                        //如果为空，直接输出null
                        if (obj == null) {
                            return "null";
                        }
                        //为普通类型，直接输出值
                        if (obj.constructor == Number || obj.constructor == Date || obj.constructor == String || obj.constructor == Boolean) {
                            var v = obj.toString();
                            var tab = isInArray ? this.__repeatStr(this.t, level - 1) : "";
                            if (obj.constructor == String || obj.constructor == Date) {
                                //时间格式化只是单纯输出字符串，而不是Date对象
                                return tab + ("\"" + v + "\"");
                            }
                            else if (obj.constructor == Boolean) {
                                return tab + v.toLowerCase();
                            }
                            else {
                                return tab + (v);
                            }
                        }

                        //写Json对象，缓存字符串
                        var currentObjStrings = [];
                        //遍历属性
                        for (var name in obj) {
                            var temp = [];
                            //格式化Tab
                            var paddingTab = this.__repeatStr(this.t, level);
                            temp.push(paddingTab);
                            //写出属性名
                            temp.push("<span class='json-key'>" + name + "</span>" + " : ");
                            var val = obj[name];
                            if (val == null) {
                                temp.push("null");
                            } else {
                                var c = val.constructor;
                                switch (c) {
                                    case String:
                                        if (true == (/http[s]?:/).test(val)) {
                                            val = "<a class='json-href' href='" + val + "' target='_blank'>" + val + "</a>";
                                        } else {
                                            val = "<span class='json-string'>" + val + "</span>";
                                        }

                                        break;
                                    case Number:
                                        //val = "<span class='json-number'>"+val+"</span>";
                                        break;
                                    default:
                                        break;
                                }
                                if (c == Array) { //如果为集合，循环内部对象
                                    temp.push(this.n + paddingTab + "[" + this.n);
                                    var levelUp = level + 2;    //层级+2

                                    var tempArrValue = [];      //集合元素相关字符串缓存片段
                                    for (var i = 0; i < val.length; i++) {
                                        //递归写对象
                                        if (String === val[i].constructor) {
                                            if (true == (/http[s]?:/i).test(val[i])) {
                                                val[i] = "<a class='json-href' href='" + val[i] + "' target='_blank'>" + val[i] + "</a>";
                                            } else {
                                                val[i] = "<span class='json-string'>" + val[i] + "</span>";
                                            }
                                        }
                                        //if (String == val[i].constructor) {
                                        //  console.log(val[i]);
                                        //}
                                        tempArrValue.push(this.__writeObj(val[i], levelUp, true));
                                    }

                                    temp.push(tempArrValue.join("," + this.n));
                                    temp.push(this.n + paddingTab + "]");
                                }
                                else if (c == Function) {
                                    temp.push("[Function]");
                                }
                                else {
                                    //递归写对象
                                    temp.push(this.__writeObj(val, level + 1));
                                }
                            }
                            //加入当前对象“属性”字符串
                            currentObjStrings.push(temp.join(""));
                        }
                        //如果Json对象是内部，就要换行格式化
                        return (level > 1 && !isInArray ? this.n : "")
                            + this.__repeatStr(this.t, level - 1) + "{" + this.n
                            + currentObjStrings.join("," + this.n)
                            + this.n + this.__repeatStr(this.t, level - 1) + "}";
                    },
                    __isArray: function (obj) {
                        if (obj) {
                            return obj.constructor == Array;
                        }
                        return false;
                    },
                    __repeatStr: function (str, times) {
                        var newStr = [];
                        if (times > 0) {
                            for (var i = 0; i < times; i++) {
                                newStr.push(str);
                            }
                        }
                        return newStr.join("");
                    }
                };
                return jsonUtil.convertToString(json);
            }
        }
    }
</script>